canopycms 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authorization/groups/loader.d.ts.map +1 -1
- package/dist/authorization/groups/loader.js +2 -5
- package/dist/authorization/groups/loader.js.map +1 -1
- package/dist/authorization/permissions/loader.d.ts.map +1 -1
- package/dist/authorization/permissions/loader.js +2 -5
- package/dist/authorization/permissions/loader.js.map +1 -1
- package/dist/branch-metadata.d.ts +10 -0
- package/dist/branch-metadata.d.ts.map +1 -1
- package/dist/branch-metadata.js +133 -32
- package/dist/branch-metadata.js.map +1 -1
- package/dist/cli/generate-ai-content.js +2702 -76
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +3806 -334
- package/dist/cli/init.js.map +1 -1
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +3 -2
- package/dist/content-store.js.map +1 -1
- package/dist/schema/schema-store.d.ts.map +1 -1
- package/dist/schema/schema-store.js +3 -2
- package/dist/schema/schema-store.js.map +1 -1
- package/dist/task-queue/task-queue.d.ts.map +1 -1
- package/dist/task-queue/task-queue.js +8 -14
- package/dist/task-queue/task-queue.js.map +1 -1
- package/dist/utils/atomic-write.d.ts +15 -0
- package/dist/utils/atomic-write.d.ts.map +1 -0
- package/dist/utils/atomic-write.js +29 -0
- package/dist/utils/atomic-write.js.map +1 -0
- package/package.json +5 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/authorization/groups/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/authorization/groups/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAoB,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAYzD;;;GAGG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAe5B;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,aAAa,EACnB,iBAAiB,GAAE,GAAG,CAAC,MAAM,CAAa,GACzC,OAAO,CAAC,aAAa,EAAE,CAAC,CA0C1B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,aAAa,EAAE,EACvB,SAAS,EAAE,YAAY,EACvB,IAAI,EAAE,aAAa,EACnB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAef"}
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Handles loading and saving internal groups from the filesystem.
|
|
5
5
|
*/
|
|
6
6
|
import { promises as fs } from 'node:fs';
|
|
7
|
-
import { join } from 'node:path';
|
|
8
7
|
import { GroupsFileSchema } from './schema';
|
|
9
8
|
import { operatingStrategy } from '../../operating-mode';
|
|
10
9
|
import { RESERVED_GROUPS } from '../helpers';
|
|
10
|
+
import { atomicWriteFile } from '../../utils/atomic-write';
|
|
11
11
|
/**
|
|
12
12
|
* Get the appropriate groups file path based on mode
|
|
13
13
|
*/
|
|
@@ -81,9 +81,6 @@ export async function loadInternalGroups(branchRoot, mode, bootstrapAdminIds = n
|
|
|
81
81
|
*/
|
|
82
82
|
export async function saveInternalGroups(branchRoot, groups, updatedBy, mode, contentVersion) {
|
|
83
83
|
const groupsPath = getGroupsFilePath(branchRoot, mode);
|
|
84
|
-
const groupsDir = join(groupsPath, '..');
|
|
85
|
-
// Ensure parent directory exists (e.g., .canopy-meta or .canopycms)
|
|
86
|
-
await fs.mkdir(groupsDir, { recursive: true });
|
|
87
84
|
const groupsFile = {
|
|
88
85
|
version: 1,
|
|
89
86
|
contentVersion: contentVersion ?? 1,
|
|
@@ -93,6 +90,6 @@ export async function saveInternalGroups(branchRoot, groups, updatedBy, mode, co
|
|
|
93
90
|
};
|
|
94
91
|
// Validate before writing
|
|
95
92
|
GroupsFileSchema.parse(groupsFile);
|
|
96
|
-
await
|
|
93
|
+
await atomicWriteFile(groupsPath, JSON.stringify(groupsFile, null, 2));
|
|
97
94
|
}
|
|
98
95
|
//# sourceMappingURL=loader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/authorization/groups/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/authorization/groups/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/authorization/permissions/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/authorization/permissions/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAWzD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAoBjC;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,cAAc,EAAE,CAAC,CAG3B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,cAAc,EAAE,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,aAAa,EACnB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,IAAI,CAAC,CAUf"}
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Handles loading and saving path permissions from the filesystem.
|
|
5
5
|
*/
|
|
6
6
|
import fs from 'node:fs/promises';
|
|
7
|
-
import path from 'node:path';
|
|
8
7
|
import { PermissionsFileSchema } from './schema';
|
|
9
8
|
import { operatingStrategy } from '../../operating-mode';
|
|
9
|
+
import { atomicWriteFile } from '../../utils/atomic-write';
|
|
10
10
|
/**
|
|
11
11
|
* Get the appropriate permissions file path based on mode
|
|
12
12
|
*/
|
|
@@ -54,9 +54,6 @@ export async function loadPathPermissions(repoRoot, mode) {
|
|
|
54
54
|
*/
|
|
55
55
|
export async function savePathPermissions(repoRoot, permissions, updatedBy, mode, contentVersion) {
|
|
56
56
|
const permissionsPath = getPermissionsFilePath(repoRoot, mode);
|
|
57
|
-
const canopyDir = path.dirname(permissionsPath);
|
|
58
|
-
// Ensure .canopycms directory exists
|
|
59
|
-
await fs.mkdir(canopyDir, { recursive: true });
|
|
60
57
|
const permissionsFile = {
|
|
61
58
|
version: 1,
|
|
62
59
|
contentVersion: contentVersion ?? 1,
|
|
@@ -66,7 +63,7 @@ export async function savePathPermissions(repoRoot, permissions, updatedBy, mode
|
|
|
66
63
|
};
|
|
67
64
|
// Validate before writing
|
|
68
65
|
PermissionsFileSchema.parse(permissionsFile);
|
|
69
|
-
await
|
|
66
|
+
await atomicWriteFile(permissionsPath, JSON.stringify(permissionsFile, null, 2));
|
|
70
67
|
}
|
|
71
68
|
/**
|
|
72
69
|
* Initialize permissions file if it doesn't exist
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/authorization/permissions/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/authorization/permissions/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAGjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAEhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE1D;;GAEG;AACH,SAAS,sBAAsB,CAAC,QAAgB,EAAE,IAAmB;IACnE,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAA;AACjE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,IAAmB;IAEnB,MAAM,eAAe,GAAG,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAE9D,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAA;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;QACtC,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACrD,OAAO,SAAS,CAAA;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,qBAAqB;QACrB,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,IAAI,CAAA;QACb,CAAC;QAED,gDAAgD;QAChD,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,KAAK,CAAC,CAAA;QACnE,MAAM,IAAI,KAAK,CACb,6BAA6B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CACxF,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,IAAmB;IAEnB,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACtD,OAAO,IAAI,EAAE,eAAe,IAAI,EAAE,CAAA;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,WAA6B,EAC7B,SAAiB,EACjB,IAAmB,EACnB,cAAuB;IAEvB,MAAM,eAAe,GAAG,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAE9D,MAAM,eAAe,GAAoB;QACvC,OAAO,EAAE,CAAC;QACV,cAAc,EAAE,cAAc,IAAI,CAAC;QACnC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS;QACT,eAAe,EAAE,WAAW;KAC7B,CAAA;IAED,0BAA0B;IAC1B,qBAAqB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;IAE5C,MAAM,eAAe,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AAClF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAgB,EAChB,MAAc,EACd,IAAmB;IAEnB,MAAM,eAAe,GAAG,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAE9D,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAA;QAChC,6BAA6B;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,qCAAqC;QACrC,MAAM,mBAAmB,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;IACvD,CAAC;AACH,CAAC"}
|
|
@@ -2,8 +2,13 @@ import type { BranchContext, BranchMetadata } from './types';
|
|
|
2
2
|
import { type OperatingMode } from './operating-mode';
|
|
3
3
|
export interface BranchMetadataFile {
|
|
4
4
|
schemaVersion: number;
|
|
5
|
+
version: number;
|
|
6
|
+
writeId?: string;
|
|
5
7
|
branch: BranchMetadata;
|
|
6
8
|
}
|
|
9
|
+
export declare class BranchMetadataConflictError extends Error {
|
|
10
|
+
constructor();
|
|
11
|
+
}
|
|
7
12
|
export declare class BranchMetadataFileManager {
|
|
8
13
|
private readonly branchRoot;
|
|
9
14
|
private readonly filePath;
|
|
@@ -20,7 +25,12 @@ export declare class BranchMetadataFileManager {
|
|
|
20
25
|
*/
|
|
21
26
|
static get(branchRoot: string, baseRoot: string): BranchMetadataFileManager;
|
|
22
27
|
private load;
|
|
28
|
+
/**
|
|
29
|
+
* Atomic write using temp-file + rename + post-write verification.
|
|
30
|
+
* Follows the same pattern as CommentStore for EFS/NFS safety.
|
|
31
|
+
*/
|
|
23
32
|
private write;
|
|
33
|
+
private withRetry;
|
|
24
34
|
save(incoming: BranchMetadataUpdate): Promise<BranchMetadataFile>;
|
|
25
35
|
/**
|
|
26
36
|
* Invalidates the registry cache so next list() call regenerates from branch.json files.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch-metadata.d.ts","sourceRoot":"","sources":["../src/branch-metadata.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"branch-metadata.d.ts","sourceRoot":"","sources":["../src/branch-metadata.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAgB,MAAM,SAAS,CAAA;AAG1E,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAMrD,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,cAAc,CAAA;CACvB;AAID,qBAAa,2BAA4B,SAAQ,KAAK;;CAKrD;AAwBD,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IAEjC,OAAO;IAMP;;;OAGG;WACU,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAa7E;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,yBAAyB;YAI7D,IAAI;IAclB;;;OAGG;YACW,KAAK;YAsEL,SAAS;IAiBjB,IAAI,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAyCvE;;OAEG;YACW,kBAAkB;CAIjC;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,WAAW,CAAC,CAAC,CAAA;CAClE;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GACvC,YAAY,MAAM,EAClB,UAAU,MAAM,KACf,yBAEF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAU,SAAS;IAC/C,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,aAAa,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,KAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAiB/B,CAAA"}
|
package/dist/branch-metadata.js
CHANGED
|
@@ -1,11 +1,37 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
1
2
|
import fs from 'node:fs/promises';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { BranchRegistry } from './branch-registry';
|
|
4
5
|
import { resolveBranchPath } from './paths';
|
|
5
|
-
import { isNotFoundError } from './utils/error';
|
|
6
|
+
import { isFileExistsError, isNotFoundError } from './utils/error';
|
|
6
7
|
const BRANCH_META_DIR = '.canopy-meta';
|
|
7
8
|
const BRANCH_META_FILE = 'branch.json';
|
|
8
9
|
const CURRENT_SCHEMA_VERSION = 1;
|
|
10
|
+
export class BranchMetadataConflictError extends Error {
|
|
11
|
+
constructor() {
|
|
12
|
+
super('Concurrent modification detected in branch metadata');
|
|
13
|
+
this.name = 'BranchMetadataConflictError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
// Module-level lock: serializes access to each branch.json within this process.
|
|
17
|
+
const fileLocks = new Map();
|
|
18
|
+
async function withFileLock(filePath, fn) {
|
|
19
|
+
while (fileLocks.has(filePath)) {
|
|
20
|
+
await fileLocks.get(filePath);
|
|
21
|
+
}
|
|
22
|
+
let resolve;
|
|
23
|
+
const lockPromise = new Promise((r) => {
|
|
24
|
+
resolve = r;
|
|
25
|
+
});
|
|
26
|
+
fileLocks.set(filePath, lockPromise);
|
|
27
|
+
try {
|
|
28
|
+
return await fn();
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
fileLocks.delete(filePath);
|
|
32
|
+
resolve();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
9
35
|
export class BranchMetadataFileManager {
|
|
10
36
|
constructor(branchRoot, baseRoot) {
|
|
11
37
|
this.branchRoot = path.resolve(branchRoot);
|
|
@@ -40,52 +66,127 @@ export class BranchMetadataFileManager {
|
|
|
40
66
|
try {
|
|
41
67
|
const raw = await fs.readFile(this.filePath, 'utf8');
|
|
42
68
|
const parsed = JSON.parse(raw);
|
|
43
|
-
|
|
69
|
+
const version = parsed.version ?? 0;
|
|
70
|
+
return { meta: parsed, version };
|
|
44
71
|
}
|
|
45
72
|
catch (err) {
|
|
46
73
|
if (isNotFoundError(err)) {
|
|
47
|
-
return null;
|
|
74
|
+
return { meta: null, version: null };
|
|
48
75
|
}
|
|
49
76
|
throw err;
|
|
50
77
|
}
|
|
51
78
|
}
|
|
52
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Atomic write using temp-file + rename + post-write verification.
|
|
81
|
+
* Follows the same pattern as CommentStore for EFS/NFS safety.
|
|
82
|
+
*/
|
|
83
|
+
async write(meta, expectedVersion) {
|
|
84
|
+
const newVersion = expectedVersion === null ? 1 : expectedVersion + 1;
|
|
85
|
+
const writeId = randomUUID();
|
|
53
86
|
const payload = {
|
|
54
87
|
...meta,
|
|
55
88
|
schemaVersion: meta.schemaVersion ?? CURRENT_SCHEMA_VERSION,
|
|
89
|
+
version: newVersion,
|
|
90
|
+
writeId,
|
|
56
91
|
};
|
|
57
92
|
await fs.mkdir(path.dirname(this.filePath), { recursive: true });
|
|
58
|
-
|
|
93
|
+
const content = JSON.stringify(payload, null, 2) + '\n';
|
|
94
|
+
if (expectedVersion === null) {
|
|
95
|
+
// New file: use exclusive create to prevent race
|
|
96
|
+
try {
|
|
97
|
+
await fs.writeFile(this.filePath, content, { flag: 'wx' });
|
|
98
|
+
return { version: newVersion, writeId };
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
if (isFileExistsError(err)) {
|
|
102
|
+
throw new BranchMetadataConflictError();
|
|
103
|
+
}
|
|
104
|
+
throw err;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Existing file: temp write + atomic rename + verification
|
|
108
|
+
const tempPath = `${this.filePath}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
109
|
+
await fs.writeFile(tempPath, content, 'utf-8');
|
|
110
|
+
try {
|
|
111
|
+
// Fast-fail optimization: check version before rename to avoid unnecessary
|
|
112
|
+
// rename + verify cycle. Not a correctness guarantee — the post-write
|
|
113
|
+
// writeId verification below is what actually detects cross-process races.
|
|
114
|
+
let currentVersion = null;
|
|
115
|
+
try {
|
|
116
|
+
const current = JSON.parse(await fs.readFile(this.filePath, 'utf-8'));
|
|
117
|
+
currentVersion = current.version ?? 0;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
currentVersion = null;
|
|
121
|
+
}
|
|
122
|
+
if (currentVersion !== expectedVersion) {
|
|
123
|
+
throw new BranchMetadataConflictError();
|
|
124
|
+
}
|
|
125
|
+
// Atomic rename
|
|
126
|
+
await fs.rename(tempPath, this.filePath);
|
|
127
|
+
// Post-write verification: confirm our write landed (catches cross-process races)
|
|
128
|
+
const afterWrite = JSON.parse(await fs.readFile(this.filePath, 'utf-8'));
|
|
129
|
+
if (afterWrite.writeId !== writeId) {
|
|
130
|
+
throw new BranchMetadataConflictError();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
await fs.unlink(tempPath).catch(() => { });
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
return { version: newVersion, writeId };
|
|
138
|
+
}
|
|
139
|
+
async withRetry(operation, maxAttempts = 5) {
|
|
140
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
141
|
+
try {
|
|
142
|
+
return await operation();
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
if (err instanceof BranchMetadataConflictError && attempt < maxAttempts) {
|
|
146
|
+
const baseDelay = Math.min(10 * Math.pow(2, attempt - 1), 100);
|
|
147
|
+
const jitter = Math.random() * baseDelay;
|
|
148
|
+
await new Promise((resolve) => setTimeout(resolve, baseDelay + jitter));
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
throw new Error('Unreachable');
|
|
59
155
|
}
|
|
60
156
|
async save(incoming) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
...
|
|
79
|
-
|
|
157
|
+
return withFileLock(this.filePath, () => this.withRetry(async () => {
|
|
158
|
+
const { meta: existing, version } = await this.load();
|
|
159
|
+
const now = new Date().toISOString();
|
|
160
|
+
const defaults = {
|
|
161
|
+
name: 'unknown',
|
|
162
|
+
status: 'editing',
|
|
163
|
+
access: {},
|
|
164
|
+
createdBy: 'unknown',
|
|
165
|
+
createdAt: now,
|
|
166
|
+
updatedAt: now,
|
|
167
|
+
};
|
|
168
|
+
const merged = {
|
|
169
|
+
schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
170
|
+
version: version ?? 0,
|
|
171
|
+
branch: {
|
|
172
|
+
...defaults,
|
|
173
|
+
...existing?.branch,
|
|
174
|
+
...incoming.branch,
|
|
175
|
+
access: {
|
|
176
|
+
...existing?.branch?.access,
|
|
177
|
+
...incoming.branch?.access,
|
|
178
|
+
},
|
|
179
|
+
// Immutable after creation
|
|
180
|
+
createdBy: existing?.branch.createdBy ?? incoming.branch?.createdBy ?? defaults.createdBy,
|
|
181
|
+
createdAt: existing?.branch.createdAt ?? defaults.createdAt,
|
|
80
182
|
},
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return merged;
|
|
183
|
+
};
|
|
184
|
+
const written = await this.write(merged, version);
|
|
185
|
+
merged.version = written.version;
|
|
186
|
+
merged.writeId = written.writeId;
|
|
187
|
+
await this.invalidateRegistry();
|
|
188
|
+
return merged;
|
|
189
|
+
}));
|
|
89
190
|
}
|
|
90
191
|
/**
|
|
91
192
|
* Invalidates the registry cache so next list() call regenerates from branch.json files.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch-metadata.js","sourceRoot":"","sources":["../src/branch-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjC,OAAO,IAAI,MAAM,WAAW,CAAA;AAG5B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAE3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"branch-metadata.js","sourceRoot":"","sources":["../src/branch-metadata.ts"],"names":[],"mappings":"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"}
|